home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
mail
/
mh
/
vmail
/
vmail.1of3
< prev
next >
Wrap
Text File
|
1991-04-05
|
55KB
|
2,099 lines
(Message mh:6)
Resent: Mon, 25 Mar 91 10:18:38 PST
Resent: qq11@uxb.liv.ac.uk (Alan Thew)
Resent: Mon, 18 Mar 91 12:21:43 PST
Resent: jcohn@nsf.gov (Johnathan Charles Cohn)
Resent: rjg@sq.com (Bob Gibson)
Resent: dak@sq.com (David Keldson)
Resent: sow@cad.luth.se (Sven-Ove Westberg)
Resent: cenkl@linus.mitre.org (Mike Cenkl)
Resent: david@scocan.sco.com (David J Fiander)
Return-Path: jamesp@metolius.WR
To: luj@ecn.purdue.edu (Jun Lu), jkm@ctt.bellcore.COM (James Mcglashan),
jmvogtle@gamera.cns.syr.edu (John M Vogtle),
cks@hawkwind.utcs.toronto.edu (Chris Siebenmann),
ccw@deakin.OZ.AU (Craig Warren), rr@mips.COM (Robert "Bob" Rodriguez),
munck@Stars.Reston.Unisys.COM (Bob Munck)
Cc: jamesp@metolius.WR.TEK.COM (James Perkins)
Subject: Vmail - version 10/87DAS
Reply-To: jamesp@metolius.WR.TEK.COM (James T. Perkins)
X-Mailer: Rand MH 6.6 - Vmail 10/87DAS - Vmailtool V1.14 91/02/27
Date: Mon, 11 Mar 91 11:37:16 PST
From: James T Perkins <jamesp@metolius.WR>
--------
Okay, folks, you asked for it. Here it is: the Tektronix Logic
Analyzers DAS Engineering local hack to Vmail, the user-friendly,
curses-based, MH-calling mail program. It is useless unless you have MH
installed and available in your PATH. It works with MH version 5.1 or
better.
There is a SunView button panel available for vmail, called vmailtool,
available from me. This helps users who can't remember which keys to
press on vmail, instead having a layer of menus, buttons, and dialog
boxes atop vmail. It is written in tooltool, a quick gadget panel
specification language. Tooltool applications run under both sunview
and openwindows, but not X11/motif or X11/uwm and their ilk.
___ ___ ___
| \ / _ \ / __| James Perkins, jamesp@metolius.wr.tek.com, (503)629-1149
| |> || |_| |\__ \ Logic Analyzers Division, DAS 9200 Engineering
|___/ |_| |_||___/ Tektronix, MS 92-725, PO Box 4600, Beaverton, OR 97076
This package is sold by weight, not by volume. Some settling of contents may
have occurred during shipping and handling.
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 3)."
# Contents: CHANGES MANIFEST Makefile READ_ME choose.c cmds.c defs.h
# find.c inc.c low.c macro.h page.c refresh.c
# Wrapped by jamesp@metolius on Mon Mar 11 11:20:04 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f CHANGES -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"CHANGES\"
else
echo shar: Extracting \"CHANGES\" \(2828 characters\)
sed "s/^X//" >CHANGES <<'END_OF_CHANGES'
X
X Modifications Summary
X
X March 8, 1991
X
X James Perkins
X jamesp@metolius.wr.tek.com
X
XThis is a summary of James Perkins' modifications to J. Zobel's 1987
Xvmail distribution.
X
XMakefile
X added targets: install, Saber, lint, tags, source, shar, depend.
X added STANDOUT_CLEANUP define.
X
Xvmail.1
X Added new commands, bugs, and history section.
X
Xdefs.h
X added "sig_type" type (SunOS Port)
X added includes of appropriate std includes.
X lint cleanup - cast to void everywhere.
X added memalign() extern for Sparc
X COMP, FORW, INC, REPL, PAGER, EDITOR, SHELL now relative pathnames.
X Added BURST, DIST, SORTM defines.
X Added CRTL_R define.
X Added externs for new functions.
X
Xmacro.h
X lint cleanup - cast to void everywhere.
X use of memalign() instead of malloc() for Sparc.
X
Xcall.c
X signal commands now of type "sig_type" (SunOS Port)
X lint cleanup - cast to void everywhere.
X execv changed to execvp so user can have personal versions of comp, etc.
X addstatus warning added where necessary.
X added burst_item(), dist_item(), sort_folder() function.
X
Xchoose.c
X lint cleanup - cast to void everywhere.
X
Xcmds.c
X signal commands now of type "sig_type" (SunOS Port)
X lint cleanup - cast to void everywhere.
X
Xfind.c
X lint cleanup - cast to void everywhere.
X
Xinc.c
X lint cleanup - cast to void everywhere.
X execl changed to execlp so user can have personal versions of inc, etc.
X
Xinit.c
X lint cleanup - cast to void everywhere.
X signal commands now of type "sig_type" (SunOS Port)
X added tstp(), tint() externs.
X added stdout_cleanup, which causes stdout to always be turned off
X when a child is spawned and waited for. It's a yucky kludge
X but necessary.
X
Xload.c
X now symlinks to mail folders are permitted, and reallocs are done right.
X use of memalign() instead of malloc() for Sparc.
X lint cleanup - cast to void everywhere.
X file name space compression now done more intelligently.
X
Xlow.c
X putchar now returns status.
X lint cleanup - cast to void everywhere.
X
Xmain.c
X lint cleanup - cast to void everywhere.
X sets and recognizes options for -burst, -dist, -sort
X added new commands to help text.
X help text length macro now dynamically sized.
X added new commands 'b', 't', 'S', '^R' to command switch.
X cast wait argument to type (union wait *)
X
Xmove.c
X lint cleanup - cast to void everywhere.
X Now removal of only item on last page of folder will send you to
X the last item on previous page of the folder, if possible.
X
Xpage.c
X lint cleanup - cast to void everywhere.
X fix bug due to walking off end of folder list when looking for the
X next/prev folder.
X
Xrefresh_folder.c
X Added new source module, which takes an existing folder and
X rescans the source listing. Needed for "^R" resync,
X 'b' burst, and 'S' sortm commands.
X
XEND OF SUMMARY
END_OF_CHANGES
if test 2828 -ne `wc -c <CHANGES`; then
echo shar: \"CHANGES\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f MANIFEST -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"MANIFEST\"
else
echo shar: Extracting \"MANIFEST\" \(684 characters\)
sed "s/^X//" >MANIFEST <<'END_OF_MANIFEST'
X File Name Archive # Description
X-----------------------------------------------------------
X CHANGES 1
X MANIFEST 1 This shipping list
X Makefile 1
X READ_ME 1
X call.c 2
X choose.c 1
X cmds.c 1
X defs.h 1
X find.c 1
X inc.c 1
X init.c 2
X load.c 3
X low.c 1
X macro.h 1
X main.c 2
X move.c 2
X page.c 1
X refresh.c 1
X vmail.1 2
END_OF_MANIFEST
if test 684 -ne `wc -c <MANIFEST`; then
echo shar: \"MANIFEST\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1936 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# vmail
X#
X# Interactive screen-based mail handler that sits on top of MH.
X#
X# Copyright (C) J. Zobel, University of Melbourne, October 1987.
X#
X# $Id: Makefile,v 1.13 91/03/11 11:19:26 jamesp Exp $
X#
X
XDESTDIR = /usr/local
XMANDIR = /usr/manl/man1
XOWNER = bin
XGROUP = lclsrc
X
XCFILES = call.c choose.c cmds.c find.c inc.c init.c load.c low.c main.c \
X move.c page.c refresh.c
X
XINCLUDES = defs.h macro.h
X
XSHARFILES = READ_ME CHANGES vmail.1 Makefile $(CFILES) $(INCLUDES)
X
XOBJS = call.o choose.o cmds.o find.o inc.o init.o load.o low.o main.o \
X move.o page.o refresh.o
X
XVERS=\"10/87DAS\"
X
X#
X# Define USDATE for U.S. date format on scan
X#
X
XDEFINES = -DVERSION=$(VERS) -DUSDATE -DSTANDOUT_CLEANUP
X
XCFLAGS = -O $(DEFINES)
X
XLDFLAGS = -s
X
XLINT = lint
XLFLAGS = $(DEFINES)
X
XLIBS = -lcurses -ltermcap
X
Xvmail: $(OBJS)
X $(CC) $(LDFLAGS) -o vmail $(OBJS) $(LIBS)
X
XSaber:
X #load $(CFLAGS) $(CFILES) $(HFILES) $(LIBS) -lc
X
Xlint:
X $(LINT) $(LFLAGS) $(CFILES) $(LIBS)
X
Xinstall : $(DESTDIR)/vmail $(MANDIR)/vmail.1
X
X$(DESTDIR)/vmail: vmail
X install -c -o $(OWNER) -g $(GROUP) -m 0751 vmail $(DESTDIR)
X
X$(MANDIR)/vmail.1 : vmail.1
X install -C -c -o $(OWNER) -g $(GROUP) -m 0644 vmail.1 $(MANDIR)
X
Xclean:
X rm -f *.[cho1] core vmail make.out tags
X
Xtags: source
X ctags -w $(CFILES) $(INCLUDES)
X
Xvmail.1 READ_ME CHANGES Makefile:
X $(CO) $(COFLAGS) $@
X
Xvmail.man: vmail.1
X nroff -man $? > $@
X
Xsource: $(CFILES) $(INCLUDES)
X
Xmakekit: $(SHARFILES)
X makekit -m $(SHARFILES)
X
Xdepend : source
X maketd $(DEFINES) $(CFILES)
X
X# DO NOT DELETE THIS LINE - make maketd DEPENDS ON IT
X# Dependencies generated at: Thu Oct 15 13:21:02 PDT 1987
X
Xcall.o: defs.h macro.h
Xchoose.o: defs.h macro.h
Xcmds.o: defs.h macro.h
Xfind.o: defs.h macro.h
Xinc.o: defs.h macro.h
Xinit.o: defs.h macro.h
Xload.o: defs.h macro.h
Xlow.o: defs.h macro.h
Xmain.o: defs.h macro.h
Xmove.o: defs.h macro.h
Xpage.o: defs.h macro.h
X
X# DO NOT ADD ANYTHING HERE - WILL GO AWAY
END_OF_Makefile
if test 1936 -ne `wc -c <Makefile`; then
echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f READ_ME -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"READ_ME\"
else
echo shar: Extracting \"READ_ME\" \(4838 characters\)
sed "s/^X//" >READ_ME <<'END_OF_READ_ME'
X$Header: /mnts/metolius/home/jamesp/usr/src/vmail/RCS/READ_ME,v 1.1 87/10/15 13:40:18 rogers Exp $
X
XVMAIL is copyright (C) J. Zobel, University of Melbourne, October 1987.
XPermission to copy and modify vmail is given in full, but copies and
Xmodified copies must contain this copyright notice.
X
X vmail is an interactive mail handler that sits on top of MH6.5.
XBecause vmail updates the MH environment by updating .mh_sequences,
Xit is not compatible with early versions of MH, although it should
Xwork with MH5 and possibly MH4.
X
X vmail has a number of advantages over raw MH. It is screen-based and
Xfaster (and more convenient) than the MH show-scan-rmm refile cycle.
XThe `scan' pages for the specified folders are loaded at start up time;
Xfurther folders may be loaded at any time. `scan' is replaced by paging
Xbetween screens of stored information, `show' by a fork() to a pager,
X`rmm' and `refile' by calls to rename (2). Other features, such as folder
Xpacking, are also faster, as most of the required information is already
Xknown to the process. vmail makes it feasible for users to organise and
Xkeep track of moderate volumes of mail without wasting too much time, and
Xis very simple to use. It has been in use at Melbourne University Computer
XScience Department for about six months without any problems, and has
Xbecome the interface of choice for many users. Users who (being new to
XUNIX) were introduced to mail with vmail have never tried the MH commands
Xthemselves, being satisfied with the vmail interface and wanting to avoid
Xthe plethora of MH functions and usages.
X
X
XTechnical Notes
X
X vmail is currently Berkeley specific, in particular use of signal(),
Xvfork(), ioctl() and union wait. It should work with most versions of MH,
Xbut makes assumptions about the structure of folders, ie, that a folder is
Xa directory containing files whose names are numbers (other files are
Xignored). By default, a .mh_profile is required to specify alternatives
Xto other defaults such as name of mail directory; the environment variable
XMH may be used to set an alternative profile. The usual assumptions are
Xmade about the format of mail items - use of fields (if present) such as
X"To:", "From:" and so on, but these also should not cause any difficulties.
X comp, repl and forw are all forked from vmail rather than imitated,
Xthere being no real time advantage to doing otherwise, but are given by
Xsingle-letter commands rather than longer commands to a shell. Most MH
Xoptions as set in the profile are ignored (most are not relevant);
Xbecause comp, repl, etc are forks rather than built-ins, this is not
Xreally a problem. The paths for these executables are in defs.h and
Xmay have to be changed.
X The most unreliable feature is probably the parsing of inc output in
Xinc.c, used when `i' is given to incorporate new mail. Because some people
Xlike to give options to inc in their profile, and because inc was too long
Xto consider rewriting, the simplest solution was to parse the inc output -
Xif the format changed this code would break.
X Some may find the mixture of stdio, curses and ioctl ugly, but it is
Xreasonably orthogonal - stdio is used when tty is in normal mode, curses
Xwhen control is required, and ioctl and signal when processes are being
Xsuspended, woken or forked.
X
XMade with "make" (no arguments). If cc does not recognize -k option,
Xvalue of make variable STACK must be changed. The compiler option
X-DUSDATE must be set if dates are to be displayed in US format.
X
XFiles
X
X READ_ME This file.
X vmail.1 Manual entry.
X Makefile Version number.
X
X defs.h Pathnames, defaults, structs, externs,
X constants. Some of these will need to be
X edited, eg locations of MH routines.
X macro.h Simple functions.
X
X call.c Forks to MH functions, editor, shell.
X choose.c Folder chooser, folder display.
X cmds.c Assorted commands.
X find.c Searching through headers for strings.
X inc.c Handles fork to inc, parsing of inc output.
X init.c Startup, interrupt handling.
X load.c Loading of folders/mail from mail directory
X into internal structures.
X low.c Some primitive functions.
X main.c High-level switch.
X move.c Commands for refile, delete, undo.
X page.c Commands associated with movement between
X pages and movement within a page.
X
XNB: All source files are formatted with tabstop=4.
X
X===============================================================================
X
XI would appreciate hearing about bugs/bug fixes/amendments/improvements/
Xadditions; any correspondence should be sent to
X
XUUCP: ...!munnari!mulga!jz
XARPA: jz%mulga.oz@uunet.uu.net
XCSNET: jz%mulga.oz@australia
X
XAny modifications received will be considered for a future release of
Xvmail. Of particular interest is SYS V compatibility and modifications
Xto suit versions of MH to which I have no access.
END_OF_READ_ME
if test 4838 -ne `wc -c <READ_ME`; then
echo shar: \"READ_ME\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f choose.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"choose.c\"
else
echo shar: Extracting \"choose.c\" \(6579 characters\)
sed "s/^X//" >choose.c <<'END_OF_choose.c'
X#ifndef lint
Xstatic char *RCS_choose_c = "$Id: choose.c,v 1.2 90/04/23 14:40:52 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- choose.c
X
X Tty-based folder selection.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X
X#define START 10 /* offset from margin of screen */
X#define RESET() toggle=false, /* left- or right- hand indicator */ \
X i=FIRST+1, /* initial row */ \
X j=START, /* initial column */ \
X f=first /* first folder */
X
XWINDOW *chooser = (WINDOW *) NULL;
X
X/* --------------------
X Display folder selection page, read commands to move around page and
X select folders.
X-------------------- */
Xvoid
Xchoose()
X{
X int n, i, j;
X bool toggle;
X folder next, f, showing(),
X first = folders, /* first folder on screen */
X last; /* folder after last folder on screen */
X char c, str[LEN], flushin();
X
X RESET();
X if(chooser == (WINDOW *) NULL)
X chooser = newwin(0, 0, 0, 0);
X last = showing(first);
Xrestart:
X while((c = flushin()) != ' ' && c != 'q') switch(c) {
X case '\r': /* go to next screen of folder names */
X case '\n':
X if(last == (folder) NULL)
X beep();
X else {
X first = last;
X last = showing(first);
X RESET();
X }
X break;
X case '\b': /* go back one page of folders */
X if(first == folders)
X beep();
X else {
X for(i=(lines-FIRST)*2 ; i > FIRST && first->prev != (folder) NULL ; i--, first=first->prev)
X ;
X last = showing(first);
X RESET();
X }
X break;
X case CTRL_L: /* redraw */
X last = showing(first);
X break;
X case 'h': /* move left */
X if(! toggle) /* already at left */
X beep();
X else {
X next = f;
X FRST_OF_NAME(next);
X next = next->prev;
X if(next == (folder) NULL)
X beep();
X else {
X f = next; j = START; toggle = false;
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X }
X }
X break;
X case 'j': /* move down */
X if(i+1 >= lines) /* at bottom */
X beep();
X else {
X next = f;
X for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
X LAST_OF_NAME(next);
X next = next->next;
X }
X if(next == (folder) NULL)
X beep();
X else {
X i++; f = next;
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X }
X }
X break;
X case 'k': /* move up */
X if(i <= FIRST+1) /* at top */
X beep();
X else {
X next = f;
X for(n=0 ; n < 2 && next != (folder) NULL ; n++) {
X FRST_OF_NAME(next);
X next = next->prev;
X }
X if(next == (folder) NULL)
X beep();
X else {
X i--; f = next;
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X }
X }
X break;
X case 'l': /* move right */
X if(toggle) /* at right */
X beep();
X else {
X next = f;
X LAST_OF_NAME(next);
X next = next->next;
X if(next == (folder) NULL)
X beep();
X else {
X f = next; j = cols/2; toggle = true;
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X }
X }
X break;
X default:
X beep();
X break;
X }
X if(c == ' ') { /* attempt to go to folder */
X if(! f->valid) { /* load folder */
X mvwaddstr(chooser, FIRST, 0, "Reading mail headers ...");
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X f->valid = true;
X (void)find_mail(f, false);
X }
X if(f->valid == EMPTY) { /* folder is empty */
X /* Go back to chooser, display "empty" message */
X (void)sprintf(str, "%s -- folder empty", f->name);
X if(first == f) /* find new first folder for page */
X if(f->next != (folder) NULL)
X first = f->next;
X else
X first = folders;
X last = showing(first);
X RESET();
X mvwaddstr(chooser, FIRST, 0, str);
X (void)wmove(chooser, i, j);
X (void)wrefresh(chooser);
X goto restart;
X }
X curflr = f;
X curmail = f->mail;
X y = FIRST;
X }
X display_page();
X}
X
X
X/* --------------------
X Show all folder names starting with "start" ending with last folder or
X when page is full.
X-------------------- */
Xfolder
Xshowing(start)
X folder start;
X{
X int count, i = FIRST+1, j = START;
X bool toggle = false;
X folder p, f;
X item m;
X char str[LEN];
X
X (void)wclear(chooser);
X mvwaddstr(chooser, TITLE, 0,
X"h,j,k,l -- left,down,up,right <return>,<bs> -- next/prev page of folders");
X mvwaddstr(chooser, STATUS, 0,
X"<space> -- select folder q -- quit, no change ^L -- refresh");
X for(p=f=start ; i < lines && f != (folder) NULL ; p=f=p->next) {
X if(f->valid) {
X /* find last page of folder, count items in folders */
X for(count=0, p=f ; p->next != (folder) NULL &&
X p->next->name == f->name ; p=p->next)
X for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
X ;
X for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
X ;
X if(count == 1)
X (void)sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
X else
X (void)sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
X p->last->number, count);
X } else
X (void)sprintf(str, "%-15s(inactive)", f->name);
X if(f == curflr) standout();
X mvwaddstr(chooser, i, j, str);
X if(f == curflr) standend();
X if(toggle)
X j = START, i++;
X else
X j = cols/2;
X toggle = ! toggle;
X }
X (void)wmove(chooser, FIRST+1, START);
X (void)wrefresh(chooser);
X return(f);
X}
X
X
XWINDOW *folwin = (WINDOW *) NULL;
X
X/* --------------------
X List all folders, active or otherwise.
X-------------------- */
Xvoid
Xlist_folders()
X{
X folder f = folders, p;
X int count, i = FIRST, half = cols/2;
X bool toggle = false;
X char str[LEN];
X WINDOW *newwin();
X item m;
X
X if(folwin == (WINDOW *) NULL)
X folwin = newwin(0, 0, 0, 0);
X (void)wclear(folwin);
X for(p=f ; ; p=f=p->next) {
X if((i+2) % lines == 0) {
X if(use_prompt(folwin) == 'q')
X break;
X i = FIRST;
X (void)wclear(folwin);
X }
X if(f == (folder) NULL) {
X (void)use_prompt(folwin);
X break;
X }
X if(f->valid) {
X /* find last page of folder, count items in folders */
X for(count=0, p=f ; p->next != (folder) NULL &&
X p->next->name == f->name ; p=p->next)
X for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
X ;
X for(m=p->mail ; m != (item) NULL ; m=m->next, count++)
X ;
X if(count == 1)
X (void)sprintf(str, "%s: %d, 1 item", f->name, f->mail->number);
X else
X (void)sprintf(str, "%s: %d-%d, %d items", f->name, f->mail->number,
X p->last->number, count);
X } else
X (void)sprintf(str, "%-15s(inactive)", f->name);
X if(f == curflr)
X (void)wstandout(folwin);
X if(toggle) {
X mvwaddstr(folwin, i, half, str);
X i++;
X } else
X mvwaddstr(folwin, i, 10, str);
X if(f == curflr)
X (void)wstandend(folwin);
X toggle = !toggle;
X }
X display_page();
X}
END_OF_choose.c
if test 6579 -ne `wc -c <choose.c`; then
echo shar: \"choose.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cmds.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cmds.c\"
else
echo shar: Extracting \"cmds.c\" \(3678 characters\)
sed "s/^X//" >cmds.c <<'END_OF_cmds.c'
X#ifndef lint
Xstatic char *RCS_cmds_c = "$Id: cmds.c,v 1.3 90/04/23 14:40:56 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- cmds.c
X
X Commands not included in page.c or move.c.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X#include <signal.h>
X
X/* --------------------
X Print the name of the alternate folder.
X-------------------- */
Xvoid
Xshow_folder()
X{
X char str[LEN];
X
X if(alternate == (folder) NULL)
X addstatus("No alternate folder", false);
X else {
X (void)sprintf(str, "alternate folder is %s\n", alternate->name);
X addstatus(str, false);
X }
X}
X
X
X/* --------------------
X Make current folder inactive - remove list of mail headers, set valid
X to false.
X-------------------- */
Xvoid
Xinactive()
X{
X folder f, p;
X
X /* find first page of folder */
X p = curflr; FRST_OF_NAME(p);
X /* find last page of folder */
X f = curflr; LAST_OF_NAME(f);
X p->next = f->next;
X p->valid = false;
X/* should free records */
X p->mail = p->last = (item) NULL;
X p->pagenum = p->pages = 1;
X if(p->next != (folder) NULL)
X p->next->prev = p;
X curflr = p;
X NEXT_VALID(curflr);
X if(curflr == (folder) NULL) {
X curflr = p;
X PREV_VALID(curflr);
X }
X if(curflr == (folder) NULL) {
X addstatus("Making last active folder inactive", true);
X to_normal();
X exit(0);
X } else {
X curmail = curflr->mail;
X y = FIRST;
X display_page();
X }
X}
X
X
X/* --------------------
X Show current mail item with fork to pager.
X-------------------- */
Xvoid
Xshow_mail()
X{
X sig_type (*oldint)(), (*oldquit)(), (*signal())();
X char str[LEN];
X union wait status;
X
X clear();
X refresh();
X top_level = false; /* used by tstp() so that right thing is done
X when process is restarted */
X if(! vfork()) {
X no_control();
X (void)sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
X execlp(pager, pager, str, 0);
X (void)printf("Warning: can't execute %s\n", pager);
X exit(0);
X }
X oldint = signal(SIGINT, SIG_IGN);
X oldquit = signal(SIGQUIT, SIG_IGN);
X (void)wait(&status);
X (void)signal(SIGINT, oldint);
X (void)signal(SIGQUIT, oldquit);
X top_level = true;
X to_control();
X hold_end(); /* wait for user to want to continue - may wish
X to read error messages */
X display_page();
X}
X
X
X/* --------------------
X Save current mail item to named file. If first non-space character
X is ~, expand it.
X-------------------- */
Xvoid
Xsave_item()
X{
X struct passwd *pwent, *getpwnam();
X char *tmp, buf[LEN], *str = buf, save[LEN];
X FILE *fi, *fo, *fopen();
X
X (void)sprintf(save, "%s.%d", curflr->name, curmail->number);
X (void)sprintf(str, "file (%s)? ", save);
X get_string(str, str);
X for(; *str == ' ' ; str++)
X ;
X for(tmp=str ; *tmp != '\0' && *tmp != ' ' ; tmp++)
X ;
X *tmp = '\0';
X if(*str != '\0') /* don't take default */
X if(*str == '~') { /* expand home directory name */
X tmp = str + 2;
X if(*(str+1) == '/')
X pwent = getpwnam(user);
X else {
X for( ; *tmp != '\0' && *tmp != '/' ; tmp++)
X ;
X *(tmp++) = '\0';
X if((pwent = getpwnam(str+1)) == (struct passwd *) NULL) {
X (void)sprintf(save, "%s: no such user", str+1);
X addstatus(save, true);
X return;
X }
X }
X (void)sprintf(save, "%s/%s", pwent->pw_dir, tmp);
X } else /* take str as given */
X (void)strcpy(save, str);
X if((fo = fopen(save, "w")) == (FILE *) NULL) {
X (void)sprintf(str, "%s: no write permission", save);
X addstatus(str, true);
X return;
X }
X addstatus("saving ...", false);
X (void)sprintf(str, "%s/%s/%d", mail_dir, curflr->name, curmail->number);
X fi = fopen(str, "r");
X while(fgets(str, LEN, fi) != (char *) NULL)
X (void)fprintf(fo, "%s", str);
X (void)fclose(fi); (void)fclose(fo);
X addstatus("saved", false);
X}
END_OF_cmds.c
if test 3678 -ne `wc -c <cmds.c`; then
echo shar: \"cmds.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f defs.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"defs.h\"
else
echo shar: Extracting \"defs.h\" \(4971 characters\)
sed "s/^X//" >defs.h <<'END_OF_defs.h'
X#ifndef lint
Xstatic char *RCS_defs_h = "$Id: defs.h,v 1.8 90/09/19 13:55:10 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- defs.h
X
X Interactive screen-based mail handler that sits on top of MH.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include <stdio.h>
X#include <string.h>
X#ifdef sun
X#include <malloc.h>
Xextern char *memalign();
X#else
Xextern char *malloc();
Xextern char *realloc();
X#endif
X#include <pwd.h>
X#include <setjmp.h>
X#include <sgtty.h>
X#include <sys/types.h>
X#include <sys/wait.h>
X#include <sys/dir.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <curses.h>
X
X/*
X * MH utilities needed by vmail
X */
X#define BURST "burst"
X#define COMP "comp"
X#define DIST "dist"
X#define FORW "forw"
X#define INC "inc"
X#define REPL "repl"
X#define SORTM "sortm"
X
X/*
X * Other things
X */
X
X#if defined(sun) || defined(ultrix)
X#define sig_type void /* Suns and Ultrix 3.x */
X#else
Xtypedef int sig_type; /* the rest of the world */
X#endif
X
X#define PAGER "more" /* default pager */
X#define EDITOR "vi" /* default editor */
X#define SHELL "/bin/csh" /* default shell */
X#define CAT "/bin/cat" /* used as `show' for pipes */
X
X#define LEN 255 /* standard string length */
X#define MAXITEMS 4097 /* number of items in folder */
X#define FPROT 0755 /* standard file protection */
X#define TITLE 0 /* title line */
X#define STATUS 1 /* status line */
X#define FIRST 2 /* first line of info */
X#define PROFILE ".mh_profile" /* default profile */
X#define CURFOL "inbox" /* default current folder */
X#define CONTEXT "context" /* default context file */
X#define SEQU ".mh_sequences" /* default .mh_sequences file */
X#define MAILDIR "Mail" /* default mail directory */
X
X#define true 1
X#define false 0
X#define EMPTY 2 /* used to mark empty folders */
X#define CTRL_L '\014'
X#define CTRL_R '\022'
X#define ESC '\033'
X#define DEL '\177'
X
X/* --------------------
X Data structures.
X
X Each folder is divided into pages of (_lines_-2) mail items, _lines_
X being the number of lines for the tty type. Pages of folders are
X stored in a doubly-linked list of pages (struct mail_folder), mail
X items (struct mail_item) in doubly liked lists of mail. Folders are
X sorted alphabetically, and pages of mail items are sorted numerically.
X-------------------- */
Xstruct mail_item {
X int number; /* number of item */
X char *title; /* header */
X struct mail_item *next, *prev; /* links to other headers */
X};
Xtypedef struct mail_item *item;
X
Xstruct mail_folder {
X char *name; /* folder name */
X int pages, pagenum; /* no. of pages, no. of page */
X bool valid; /* true if folder active */
X item mail, last; /* first and last mail items for page
X - NULL if folder not active */
X struct mail_folder *next, *prev; /* linked list of folders */
X};
Xtypedef struct mail_folder *folder;
X
X
Xextern folder folders, /* list of all folders */
X curflr, /* current folder */
X alternate; /* alternate folder */
Xextern item curmail; /* current mail */
Xextern char **environ,
X *user, /* user name */
X *pager, /* desired pager */
X *editor, /* desired editor */
X *shell, /* desired shell */
X *mail_dir, /* mail directory */
X *context; /* context file */
Xextern int y, /* current Y co-ordinate (for curses) */
X folder_protect, /* protection for folders */
X lines, /* lines per screen */
X cols; /* cols per screen */
Xextern bool top_level, /* flag used to see if process stopped
X from within subprocess */
X do_flush, /* true if input is to be flushed */
X comp_args, /* true if calls to comp needs args */
X repl_args, /* true if calls to repl needs args */
X forw_args, /* true if calls to forw needs args */
X burst_args, /* true if calls to burst needs args */
X dist_args, /* true if calls to dist needs args */
X sort_args; /* true if calls to sortm needs args */
Xextern jmp_buf env;
X
X#include "macro.h"
X
Xfolder find_mail();
Xextern char *sprintf();
Xvoid add_page_header(), addstatus(), choose(), comp(), create_mail_record(),
X cursor_down(), cursor_up(),
X display_page(), delete_item(), deleteline(), edit(),
X find_folders(), flatten(), forw(), get_env(),
X get_home(), read_profile(), get_string(), get_title(),
X goto_folder(), call_shell(), goto_incorp_folder(),
X goto_next_folder(), goto_prev_folder(), hold_end(),
X inactive(), inc(), init(), list_folders(),
X mark_valid_folders(), move_item(), next_page(),
X no_control(), pack_folder(), prev_page(), repl(),
X refresh_folder(), save_item(), search(), show_folder(),
X show_mail(), show_title(), to_control(), to_normal(),
X undo(), pack(), cursor_first(), cursor_middle(),
X cursor_last(), goto_first_page(), goto_last_page(),
X squash(), get_date(), process_args(), do_pipe(),
X sort_folder(), burst_item(), dist_item();
Xbool change_item();
END_OF_defs.h
if test 4971 -ne `wc -c <defs.h`; then
echo shar: \"defs.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f find.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"find.c\"
else
echo shar: Extracting \"find.c\" \(1985 characters\)
sed "s/^X//" >find.c <<'END_OF_find.c'
X#ifndef lint
Xstatic char *RCS_find_c = "$Id: find.c,v 1.2 90/04/23 14:41:04 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- find.c
X
X Searching titles for strings.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X
Xstatic char str[LEN] = "^.*";
X
X/* --------------------
X Get string for searching, either forwards (forwards = true) or backwards
X (forwards = false). Then scan mail headers using regex().
X-------------------- */
Xvoid
Xsearch(forwards)
X int forwards;
X{
X char s1[LEN], *s2, *re_comp();
X int i;
X bool found = false;
X folder f;
X item m;
X
X get_string((forwards) ? "/" : "?", s1);
X if((i = strlen(s1)) > 0) {
X /* new search string */
X (void)strcpy(str+3, s1);
X str[i+=3] = '.', str[++i] = '*', str[++i] = '\0';
X } else if(strlen(str+3) == 0) {
X addstatus("", false);
X return;
X }
X if((s2 = re_comp(str)) != (char *) NULL) {
X addstatus(s2, false);
X return;
X }
X addstatus("searching ...", false);
X if(forwards)
X for(i=y+1, f=curflr, m=curmail->next ; ! found && m != curmail ; ) {
X if(m == (item) NULL) {
X f = f->next; NEXT_VALID(f);
X if(f == (folder) NULL) {
X f = folders;
X NEXT_VALID(f);
X }
X m = f->mail;
X i = FIRST;
X }
X if(! (found = re_exec(m->title)))
X m = m->next, i++;
X }
X else
X for(i=y-1, f=curflr, m=curmail->prev ; ! found && m != curmail ; ) {
X if(m == (item) NULL) {
X f = f->prev; PREV_VALID(f);
X if(f == (folder) NULL) {
X /* find last folder */
X for(f=folders ; f->next != (folder) NULL ; f=f->next)
X ;
X PREV_VALID(f);
X }
X /* find last mail item with count */
X for(i=FIRST, m=f->mail ; m->next != (item) NULL ; i++,m=m->next)
X ;
X }
X if(! (found = re_exec(m->title)))
X m = m->prev, i--;
X }
X curmail = m, y = i;
X if(f != curflr) {
X curflr = f;
X display_page();
X } else if(! found) /* come back to current folder (known to be valid) */
X addstatus("pattern not found", true);
X else
X addstatus("", false);
X}
END_OF_find.c
if test 1985 -ne `wc -c <find.c`; then
echo shar: \"find.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f inc.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"inc.c\"
else
echo shar: Extracting \"inc.c\" \(3762 characters\)
sed "s/^X//" >inc.c <<'END_OF_inc.c'
X#ifndef lint
Xstatic char *RCS_inc_c = "$Id: inc.c,v 1.3 90/04/23 14:41:07 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- inc.c
X
X Incorporate new mail with "inc", parse output and update appropriate
X folder-pages.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X
X#define INCORP "Incorporating new mail into "
X#define TAIL "...\n"
X
Xstatic folder isfol; /* folder into which mail is being incorporated */
Xstatic item ismail; /* last item of mail on isfol page */
Xstatic int count; /* number of items on isfol page */
X
X/* --------------------
X Call, inc, parse output to work out what items have been read and into
X what folders.
X-------------------- */
Xvoid
Xinc()
X{
X char str[LEN], line[LEN], *tmp, *fgets();
X FILE *pp, *fdopen();
X int num, pd[2], len = strlen(INCORP), numbers();
X bool redraw = true;
X union wait status;
X
X addstatus("incorporating mail ... ", true);
X (void)pipe(pd);
X if(! vfork()) {
X (void)close(pd[0]);
X (void)dup2(pd[1], 1);
X (void)close(pd[1]);
X (void)dup2(1, 2);
X execlp(INC, "inc", 0);
X }
X (void)close(pd[1]);
X if((pp = fdopen(pd[0], "r")) == (FILE *) NULL) {
X addstatus("panic, can't incorporate mail", true);
X return;
X }
X while((tmp = fgets(str, LEN, pp)) != (char *) NULL) /* read "inc" output */
X if(strncmp(tmp, INCORP, len) == 0) { /* reading into new folder */
X tmp += len;
X tmp[strlen(tmp)-strlen(TAIL)] = '\0';
X goto_incorp_folder(tmp);
X if(isfol == (folder) NULL) {
X (void)sprintf(line, "can't go to folder %s", tmp);
X addstatus(line, true);
X redraw = false;
X break;
X } else {
X (void)sprintf(line, "incorporating mail into folder %s", tmp);
X addstatus(line, true);
X }
X } else if(num = numbers(tmp)) /* continuing to read into folder */
X create_mail_record(num);
X else if(strlen(str) > 2) { /* vmail is confused - break */
X str[strlen(str)-1] = '\0';
X addstatus(str, true);
X redraw = false;
X break;
X }
X if(redraw) {
X if(isfol != curflr)
X alternate = curflr;
X curflr = isfol;
X curmail = ismail;
X y = count;
X display_page();
X }
X (void)fclose(pp);
X (void)wait(&status);
X}
X
X
X/* --------------------
X Extract the first number from str.
X-------------------- */
Xint
Xnumbers(str)
X char *str;
X{
X char save, *tmp;
X int i;
X
X for(; *str == ' ' ; str++)
X ;
X for(tmp=str ; *str >= '0' && *str <= '9' ; str++)
X ;
X save = *str, *str = '\0', i = atoi(tmp), *str = save;
X return(i);
X}
X
X
X/* --------------------
X Find the folder into which mail is being incorporated, set isfol,
X ismail, count.
X-------------------- */
Xvoid
Xgoto_incorp_folder(str)
X char *str;
X{
X folder create_folder();
X
X GOTO_NAME(isfol, str);
X if(isfol == (folder) NULL) { /* new folder */
X isfol = create_folder(str);
X isfol->valid = true;
X ismail = (item) NULL;
X count = FIRST-1;
X } else {
X if(! isfol->valid) {
X isfol->valid = true;
X (void)find_mail(isfol, false);
X }
X /* find last appropriate folder record */
X LAST_OF_NAME(isfol);
X for(count=FIRST, ismail=isfol->mail ; ismail->next != (item) NULL ;
X count++, ismail=ismail->next)
X ;
X }
X}
X
X
X/* --------------------
X Create and insert new item record into isfol, may need to create new page.
X-------------------- */
Xvoid
Xcreate_mail_record(num)
X int num;
X{
X item m;
X folder new_folder();
X
X m = NEW(mail_item);
X get_title(isfol, m, num);
X m->next = (item) NULL;
X if(count > lines) {
X /* create new folder record */
X isfol = new_folder(isfol);
X ismail = (item) NULL;
X count = FIRST;
X } else
X count++;
X if(ismail == (item) NULL) {
X /* new record, possibly new folder */
X m->prev = (item) NULL;
X isfol->mail = isfol->last = m;
X } else {
X /* insert at end of list of mail items */
X m->prev = ismail;
X ismail->next = isfol->last = m;
X }
X ismail = m;
X}
END_OF_inc.c
if test 3762 -ne `wc -c <inc.c`; then
echo shar: \"inc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f low.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"low.c\"
else
echo shar: Extracting \"low.c\" \(3352 characters\)
sed "s/^X//" >low.c <<'END_OF_low.c'
X#ifndef lint
Xstatic char *RCS_low_c = "$Id: low.c,v 1.3 90/04/23 14:41:24 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- low.c
X
X Low level screen update and data structure update routines, other
X similar stuff.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X
X/* --------------------
X Get string from terminal (visibly).
X-------------------- */
Xvoid
Xget_string(mes, str)
X char *mes, *str;
X{
X char c;
X int i;
X
X move(STATUS, 0);
X clrtoeol();
X addstr(mes);
X refresh();
X for(i=0 ; (c = getchar()) != '\n' && c != '\r' && c != ESC ; )
X if(i > 0 && c == '\b') {
X i--;
X mvaddch(STATUS, strlen(mes)+i, ' ');
X move(STATUS, strlen(mes)+i);
X refresh();
X } else if(c != '\b') {
X str[i++] = c;
X addch(c);
X refresh();
X }
X str[i] = '\0';
X move(y, 0);
X}
X
X
X/* --------------------
X Put string on status line.
X-------------------- */
Xvoid
Xaddstatus(str, stand)
X char *str;
X bool stand;
X{
X move(STATUS, 0);
X clrtoeol();
X if(stand)
X standout(); /* doesn't do anything? */
X addstr(str);
X if(stand)
X standend();
X move(y, 0);
X refresh();
X}
X
X
X/* --------------------
X Fudge deleteline because curses wont delete the line immediately
X after a ^Z, and because it doesnt clear the last line of the screen.
X-------------------- */
Xvoid
Xdeleteline()
X{
X mvaddstr(y, 0, "scribble");
X deleteln();
X move(FIRST+lines-1, 0);
X clrtoeol();
X move(y, 0);
X}
X
X
Xint
Xputch(c)
X char c;
X{
X return(putchar(c)); /* turn macro into routine */
X}
X
X
X/* --------------------
X Put prompt on screen, wait for getchar().
X-------------------- */
Xint
Xuse_prompt(win)
X WINDOW *win;
X{
X int c = (cols-42)/2;
X
X mvwaddstr(win,FIRST+lines-1,c,"-- hit space to continue, q to quit -- ");
X (void)wrefresh(win);
X return(getchar());
X}
X
X
X/* --------------------
X Put info for mail item on screen at row i.
X-------------------- */
Xvoid
Xshow_title(str, i, mail)
X char *str;
X int i;
X item mail;
X{
X (void)sprintf(str, "%4d%s", mail->number, mail->title);
X mvaddstr(i, 0, str);
X}
X
X
X/* --------------------
X Put header for page at top of screen.
X-------------------- */
Xvoid
Xadd_page_header(str)
X char *str;
X{
X (void)sprintf(str, "%s (page %d of %d) - Type 'h' for help ", curflr->name, curflr->pagenum,
X curflr->pages);
X mvaddstr(TITLE, 0, str);
X}
X
X
X/* --------------------
X Flush typeahead.
X-------------------- */
Xchar
Xflushin()
X{
X struct sgttyb sg;
X
X if(do_flush) {
X (void)ioctl(0, TIOCGETP, (caddr_t)&sg);
X (void)ioctl(0, TIOCSETP, (caddr_t)&sg);
X }
X return(getchar());
X}
X
X
X/* --------------------
X Print message, wait for getchar();
X-------------------- */
Xvoid
Xhold_end()
X{
X tputs(SO, 1, putch);
X (void)printf("-- any character to continue --");
X tputs(SE, 1, putch);
X (void)fflush(stdout);
X (void)getchar();
X}
X
X
X#define ctol(c) (((c) >= 'A' && (c) <= 'Z') ? c-'A'+'a' : c)
X
X/* --------------------
X Case independent strncmp.
X-------------------- */
Xlstrncmp(s1, s2, n)
X char *s1, *s2;
X int n;
X{
X for( ; ctol(*s1) == ctol(*s2) && n > 0 ; s1++, s2++, n--)
X ;
X return((n > 0) ? *s1 - *s2 : 0);
X}
X
X
X/* --------------------
X String processing - more useful form of index.
X Skip current non-white then skip white, replacing by null.
X-------------------- */
Xchar *
Xnext_token(t)
X char *t;
X{
X for( ; *t != ' ' && *t != '\t' && *t != '\0' ; t++)
X ;
X for( ; *t == ' ' || *t == '\t' ; t++)
X *t = '\0';
X return(t);
X}
END_OF_low.c
if test 3352 -ne `wc -c <low.c`; then
echo shar: \"low.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f macro.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"macro.h\"
else
echo shar: Extracting \"macro.h\" \(1229 characters\)
sed "s/^X//" >macro.h <<'END_OF_macro.h'
X#ifndef lint
Xstatic char *RCS_macro_h = "$Id: macro.h,v 1.2 90/04/23 14:41:27 rogers Exp $";
X#endif
X
X/* --------------------
X macro.h -- assorted functions
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X/*
X * functions for allocating memory. Note that on sparc implementations,
X * we use memalign for mallocing structs, as it is less likely to
X * return a bad pointer.
X */
X
X#define beep() (void)printf("%c", 007)
X#define NEWSTR(N) (char *) malloc((unsigned)(N))
X#ifdef sparc
X#define NEW(S) (struct S *) memalign((unsigned)8,(unsigned)sizeof(struct S))
X#else
X#define NEW(S) (struct S *) malloc((unsigned)sizeof(struct S))
X#endif
X
X/* --------------------
X Moving between pages of mail items.
X-------------------- */
X#define PREV_VALID(F) for(; F != (folder) NULL && ! F->valid ; F=F->prev)
X#define NEXT_VALID(F) for(; F != (folder) NULL && ! F->valid ; F=F->next)
X#define FRST_OF_NAME(F) for(; F->prev != (folder) NULL && \
X F->name == F->prev->name ; F=F->prev)
X#define LAST_OF_NAME(F) for(; F->next != (folder) NULL && \
X F->name == F->next->name ; F=F->next)
X#define GOTO_NAME(F,S) for(F=folders ; F != (folder) NULL && \
X strcmp(S, F->name) != 0 ; F=F->next)
END_OF_macro.h
if test 1229 -ne `wc -c <macro.h`; then
echo shar: \"macro.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f page.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"page.c\"
else
echo shar: Extracting \"page.c\" \(8170 characters\)
sed "s/^X//" >page.c <<'END_OF_page.c'
X#ifndef lint
Xstatic char *RCS_page_c = "$Id: page.c,v 1.2 90/04/23 14:41:42 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- page.c
X
X Routines for paging between folders.
X
X Copyright (C) J. Zobel, University of Melbourne, October 1987.
X-------------------- */
X
X#include "defs.h"
X
X/* --------------------
X Clear screen, show current page of mail items.
X-------------------- */
Xvoid
Xdisplay_page()
X{
X int i;
X item mail;
X char str[LEN];
X
X clear();
X add_page_header(str);
X for(i=FIRST, mail=curflr->mail ; mail != (item) NULL ; i++, mail=mail->next)
X show_title(str, i, mail);
X move(y, 0);
X refresh();
X}
X
X
X/* --------------------
X Find previous valid page of mail items (times count).
X-------------------- */
Xvoid
Xprev_page(count, display)
X int count;
X bool display;
X{
X bool show = false;
X folder f, p = curflr;
X
X for( ; count > 0 ; count--) {
X f = curflr->prev; PREV_VALID(f);
X if(f == (folder) NULL)
X break;
X else {
X show = true;
X y = FIRST;
X curflr = f;
X curmail = curflr->mail;
X }
X }
X if(p != curflr)
X alternate = p;
X if(display) {
X if(show)
X display_page();
X if(f == (folder) NULL)
X addstatus("first active page", true);
X }
X}
X
X
X/* --------------------
X Find next valid page of mail items (times count).
X-------------------- */
Xvoid
Xnext_page(count, display)
X int count;
X bool display;
X{
X bool show = false;
X folder f, p = curflr;
X
X for( ; count > 0 ; count--) {
X f = curflr->next; NEXT_VALID(f);
X if(f == (folder) NULL)
X break;
X else {
X show = true;
X y = FIRST;
X curflr = f;
X curmail = curflr->mail;
X }
X }
X if(p != curflr)
X alternate = p;
X if(display) {
X if(show)
X display_page();
X if(f == (folder) NULL)
X addstatus("last active page", true);
X }
X}
X
X
X/* --------------------
X Move cursor up count lines.
X-------------------- */
Xvoid
Xcursor_up(count)
X int count;
X{
X bool redraw = false;
X
X addstatus("", false); /* clear status line */
X for( ; count > 0 ; count--)
X if(curmail->prev == (item) NULL) {
X if(curflr->prev == (folder) NULL ||
X curflr->name != curflr->prev->name) {
X addstatus("first page of folder", true);
X break;
X } else {
X redraw = true;
X prev_page(1, false);
X /* find last mail item on page */
X for( ; curmail->next != (item) NULL ; y++)
X curmail=curmail->next;
X }
X } else {
X y--;
X curmail = curmail->prev;
X }
X if(redraw)
X display_page();
X else {
X move(y, 0);
X refresh();
X }
X}
X
X
X/* --------------------
X Move cursor down count lines.
X-------------------- */
Xvoid
Xcursor_down(count)
X int count;
X{
X bool redraw = false;
X
X addstatus("", false); /* clear status line */
X for( ; count > 0 ; count--)
X if(curmail->next == (item) NULL) {
X if(curflr->next == (folder) NULL ||
X curflr->name != curflr->next->name) {
X addstatus("last page of folder", true);
X break;
X } else {
X redraw = true;
X next_page(1, false);
X }
X } else {
X y++;
X curmail = curmail->next;
X }
X if(redraw)
X display_page();
X else {
X move(y, 0);
X refresh();
X }
X}
X
X
X/* --------------------
X Go to next folder, make active if not so already.
X-------------------- */
Xvoid
Xgoto_next_folder(count)
X int count;
X{
X bool changed = false;
X folder f, p = curflr;
X
X for( ; count > 0 ; count--) {
X /* skip other pages of current folder */
X for(f=p ; p->next != (folder) NULL && p->next->name == f->name ;
X p=p->next)
X ;
X if(p->next == (folder) NULL) {
X addstatus("last folder", true);
X break;
X } else {
X changed = true;
X p = p->next;
X }
X }
X if(changed) {
X do {
X if(!p->valid) {
X p->valid = true;
X addstatus("reading mail headers ...", true);
X (void)find_mail(p, false);
X }
X if(p->valid == EMPTY)
X p = p->next;
X } while(p != (folder) NULL && p->valid != true);
X if(p == (folder) NULL)
X addstatus("can't go forward that many folders", true);
X else {
X alternate = curflr;
X curflr = p;
X curmail = p->mail;
X y = FIRST;
X display_page();
X }
X }
X}
X
X
X/* --------------------
X Goto previous folder, make active if not so already.
X-------------------- */
Xvoid
Xgoto_prev_folder(count)
X int count;
X{
X bool changed = false;
X folder f, p = curflr;
X
X for( ; count > 0 ; count--) {
X /* skip other pages of current folder */
X for(f=p ; p->prev != (folder) NULL && p->prev->name == f->name ;
X p=p->prev)
X ;
X if(curflr->prev == (folder) NULL || p->prev == (folder) NULL) {
X addstatus("first folder", true);
X break;
X } else {
X changed = true;
X p = p->prev;
X }
X }
X if(changed) {
X do {
X if(!p->valid) {
X p->valid = true;
X addstatus("reading mail headers ...", true);
X (void)find_mail(p, false);
X }
X if(p->valid == EMPTY)
X p = p->prev;
X } while(p != (folder) NULL && p->valid != true);
X if(p == (folder) NULL)
X addstatus("can't go back that many folders", true);
X else {
X /* skip other pages of current folder */
X for(f=p ; p->prev != (folder) NULL &&
X p->prev->name == f->name ; p=p->prev)
X ;
X alternate = curflr;
X curflr = p;
X curmail = p->mail;
X y = FIRST;
X display_page();
X }
X }
X}
X
X
X/* --------------------
X Make new folder current as specified - read from terminal (get_name =
X true) or use value in alternate (get_name = false).
X-------------------- */
Xvoid
Xgoto_folder(get_name)
X bool get_name;
X{
X char buf[LEN], *str = buf;
X folder f;
X int i;
X
X if(get_name || alternate == (folder) NULL) {
X /* no alternate folder */
X get_string("folder? ", str);
X for(i=0 ; *str == ' ' ; i++, str++)
X ;
X for(; i < LEN && buf[i] != ' ' && buf[i] != '\0' ; i++)
X ;
X if(i < LEN)
X buf[i] = '\0';
X GOTO_NAME(f, str);
X if(f == (folder) NULL) {
X addstatus("no such folder", true);
X return;
X }
X if(!f->valid) {
X f->valid = true;
X addstatus("reading mail headers ...", true);
X (void)find_mail(f, false);
X if(f->valid == EMPTY) {
X (void)sprintf(str, "%s -- folder empty", f->name);
X addstatus(str, true);
X return;
X }
X }
X } else
X f = alternate;
X if(f == curflr)
X addstatus("already in that folder", true);
X else {
X alternate = curflr;
X curflr = f;
X curmail = f->mail;
X y = FIRST;
X display_page();
X }
X}
X
X
X/* --------------------
X Go to first line of page, as offset by count.
X-------------------- */
Xvoid
Xcursor_first(count)
X int count;
X{
X item m = curflr->mail;
X
X addstatus("", false); /* clear status line */
X for(y=FIRST ; m != (item) NULL && count > 1 ; count--, y++, m=m->next)
X ;
X if(m == (item) NULL)
X beep();
X else {
X curmail = m;
X move(y, 0);
X refresh();
X }
X}
X
X
X/* --------------------
X Go to middle line of page.
X-------------------- */
Xvoid
Xcursor_middle()
X{
X item m, p;
X bool tog = false;
X
X addstatus("", false); /* clear status line */
X /* find middle of page - p traverses page at half speed */
X for(y=FIRST, m=p=curflr->mail ; m != (item) NULL ; m=m->next, tog= !tog)
X if(tog) {
X y++;
X p = p->next;
X }
X curmail = p;
X move(y, 0);
X refresh();
X}
X
X
X/* --------------------
X Go to last line of page, as offset by count.
X-------------------- */
Xvoid
Xcursor_last(count)
X int count;
X{
X item m = curflr->mail;
X
X addstatus("", false); /* clear status line */
X /* find last item, including y-value */
X for(y=FIRST ; m->next != (item) NULL ; y++, m=m->next)
X ;
X for(; m != (item) NULL && count > 1 ; count--, y--, m=m->prev)
X ;
X if(m == (item) NULL)
X beep();
X else {
X curmail = m;
X move(y, 0);
X refresh();
X }
X}
X
X
X/* --------------------
X Go to first page. ***should use count as offset***
X-------------------- */
Xvoid
Xgoto_first_page()
X{
X folder f;
X
X f = folders; NEXT_VALID(f);
X if(f == (folder) NULL) {
X /* no valid folders - bleah?! */
X addstatus("no valid folders, exiting", true);
X to_normal();
X exit(1);
X } else if(f != curflr) {
X alternate = curflr;
X curflr = f;
X curmail = f->mail;
X y = FIRST;
X display_page();
X }
X}
X
X
X/* --------------------
X Go to last page. ***should use count as offset***
X-------------------- */
Xvoid
Xgoto_last_page()
X{
X folder f, p;
X
X for(f=folders ; f != (folder) NULL ; f=f->next)
X if(f->valid)
X p = f;
X if(p == (folder) NULL) {
X /* no valid folders - bleah?! */
X addstatus("no valid folders, exiting", true);
X to_normal();
X exit(1);
X } else if(p != curflr) {
X alternate = curflr;
X curflr = p;
X curmail = p->mail;
X y = FIRST;
X display_page();
X }
X}
END_OF_page.c
if test 8170 -ne `wc -c <page.c`; then
echo shar: \"page.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f refresh.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"refresh.c\"
else
echo shar: Extracting \"refresh.c\" \(1896 characters\)
sed "s/^X//" >refresh.c <<'END_OF_refresh.c'
X#ifndef lint
Xstatic char *RCS_refresh_folder_c = "$Id: refresh.c,v 1.1 90/09/19 14:00:09 rogers Exp $";
X#endif
X
X/* --------------------
X vmail -- refresh_folder.c
X
X Routine for rescanning a folder.
X
X James Perkins 9-19-90 (jamesp@metolius.wr.tek.com)
X-------------------- */
X
X#include "defs.h"
X
X/* --------------------
X Refresh the folder's display - reread the scan listing
X-------------------- */
Xvoid
Xrefresh_folder()
X{
X folder f, p;
X char *curfname = curflr->name;
X char str[LEN];
X
X /*
X * INACTIVATE CURRENT FOLDER
X */
X
X /* find first, last page of folder */
X p = curflr; FRST_OF_NAME(p);
X f = curflr; LAST_OF_NAME(f);
X
X /* free (should really, actually free here...) */
X p->next = f->next;
X p->valid = false;
X p->mail = p->last = (item) NULL;
X p->pagenum = p->pages = 1;
X if(p->next != (folder) NULL)
X p->next->prev = p;
X
X /* Get new current folder in case the re-scan comes up empty */
X curflr = p;
X NEXT_VALID(curflr);
X if(curflr == (folder) NULL) {
X curflr = p;
X PREV_VALID(curflr);
X }
X if(curflr == (folder) NULL) {
X /* Note: just made the last folder inactive ... */
X }
X
X /*
X * GOTO ORIGINAL, STARTING FOLDER NAME
X */
X
X GOTO_NAME(f, curfname);
X if(f == (folder) NULL) {
X addstatus("no such folder", true);
X return;
X }
X if(!f->valid) {
X f->valid = true;
X addstatus("re-reading mail headers ...", true);
X (void)find_mail(f, false);
X if(f->valid == EMPTY) {
X /* go to another valid folder (found by code above) */
X if (curflr == (folder) NULL) {
X /* No other valid folder to go to! */
X addstatus("Last active folder is empty", true);
X to_normal();
X exit(0);
X }
X (void)sprintf(str, "%s -- folder empty", f->name);
X addstatus(str, true);
X f = curflr;
X }
X }
X else {
X addstatus("internal error: folder unexpectedly valid!", true);
X to_normal();
X exit(0);
X }
X
X alternate = (folder) NULL;
X curflr = f;
X curmail = f->mail;
X y = FIRST;
X display_page();
X}
END_OF_refresh.c
if test 1896 -ne `wc -c <refresh.c`; then
echo shar: \"refresh.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 3 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0